/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

using Galaxium.Protocol.Msn.Soap.BodyParts;
using Galaxium.Protocol.Msn.Soap.Headers;

namespace Galaxium.Protocol.Msn.Soap
{
	// http://msnpiki.msnfanatic.com/index.php/MSNP13:Contact_List
	
	public enum ABView { Full }
	
	[WebServiceBinding (Name="soap:Envelope", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
	public class ABService : MsnSoapService
	{
		public ABApplicationHeader appHeader;
		public ABAuthHeader authHeader;
		public ServiceHeader serviceHeader;
		
		public ABService (MsnSession session)
			: base (session)
		{
			AddUrl ("http://contacts.msn.com/abservice/abservice.asmx");
			AddUrl ("https://omega.contacts.msn.com/abservice/abservice.asmx");
			AddUrl ("https://by4.omega.contacts.msn.com/abservice/abservice.asmx");
			
			appHeader = new ABApplicationHeader ();
			authHeader = new ABAuthHeader (session);
		}
		
		void ProcessServiceHeader ()
		{
			if (serviceHeader != null)
			{
				if (!string.IsNullOrEmpty (serviceHeader.PreferredHostName))
				{
					UpdateDomain (serviceHeader.PreferredHostName);
					Session.SharingService.UpdateDomain (serviceHeader.PreferredHostName);
				}
				if (serviceHeader.CacheKeyChanged)
					appHeader.CacheKey = serviceHeader.CacheKey;
				
				serviceHeader = null;
			}
		}
		
		internal void UpdateDomain (string domain)
		{
			SwitchUrl ("http://" + domain + "/abservice/abservice.asmx");
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABAdd", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public string ABAdd (ABInfo abInfo)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Initial;
			object[] results = this.Invoke ("ABAdd", new object[] { abInfo });
			ProcessServiceHeader ();
			return (string)results[0];
		}
		
		public IAsyncResult BeginABAdd (ABInfo abInfo, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Initial;
			return this.BeginInvoke ("ABAdd", new object[] { abInfo }, callback, asyncState);
		}
		
		public string EndABAdd (IAsyncResult asyncResult)
		{
			object[] results = this.EndInvoke (asyncResult);
            return (string)results[0];
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABFindAll", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public ABFindAllResult ABFindAll (Guid abId, ABView abView, bool deltasOnly, DateTime lastChange)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Initial;
			object[] results = this.Invoke ("ABFindAll", new object[] { abId, abView, deltasOnly, lastChange });
			ProcessServiceHeader ();
			return (ABFindAllResult)results[0];
		}
		
		public IAsyncResult BeginABFindAll (Guid abId, ABView abView, bool deltasOnly, DateTime lastChange, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Initial;
			return this.BeginInvoke ("ABFindAll", new object[] { abId, abView, deltasOnly, lastChange }, callback, asyncState);
		}
		
		public ABFindAllResult EndABFindAll (IAsyncResult asyncResult)
		{
			object[] results = this.EndInvoke (asyncResult);
            return (ABFindAllResult)results[0];
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABContactAdd", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public ABContactAddResult ABContactAdd (Guid abId, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts, ABContactAddOptions options)
		{
			appHeader.PartnerScenario = ABPartnerScenario.ContactSave;
			object[] results = this.Invoke ("ABContactAdd", new object[] { abId, contacts, options });
			ProcessServiceHeader ();
			return (ABContactAddResult)results[0];
		}
		
		public IAsyncResult BeginABContactAdd (Guid abId, ABContactCollection contacts, ABContactAddOptions options, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.ContactSave;
			return this.BeginInvoke ("ABContactAdd", new object[] { abId, contacts, options }, callback, asyncState);
		}
		
		public ABContactAddResult EndABContactAdd (IAsyncResult asyncResult)
		{
			object[] results = this.EndInvoke (asyncResult);
			return (ABContactAddResult)results[0];
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABGroupContactAdd", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public ABGroupContactAddResult ABGroupContactAdd (Guid abId, GroupFilter groupFilter, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts, ABGroupContactAddOptions groupContactAddOptions)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			object[] results = this.Invoke ("ABGroupContactAdd", new object[] { abId, groupFilter, contacts, groupContactAddOptions });
			ProcessServiceHeader ();
			return (ABGroupContactAddResult)results[0];
		}
		
		public IAsyncResult BeginABGroupContactAdd (Guid abId, GroupFilter groupFilter, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts, ABGroupContactAddOptions groupContactAddOptions, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			return this.BeginInvoke ("ABGroupContactAdd", new object[] { abId, groupFilter, contacts, groupContactAddOptions }, callback, asyncState);
		}
		
		public ABGroupContactAddResult EndABGroupContactAdd (IAsyncResult asyncResult)
		{
			object[] results = this.EndInvoke (asyncResult);
			return (ABGroupContactAddResult)results[0];
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABContactUpdate", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public void ABContactUpdate (Guid abId, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Timer;
			this.Invoke ("ABContactUpdate", new object[] { abId, contacts });
			ProcessServiceHeader ();
		}
		
		public IAsyncResult BeginABContactUpdate (Guid abId, ABContactCollection contacts, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Timer;
			return this.BeginInvoke ("ABContactUpdate", new object[] { abId, contacts }, callback, asyncState);
		}
		
		public void EndABContactUpdate (IAsyncResult asyncResult)
		{
			this.EndInvoke (asyncResult);
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABContactDelete", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public void ABContactDelete (Guid abId, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Timer;
			this.Invoke ("ABContactDelete", new object[] { abId, contacts });
			ProcessServiceHeader ();
		}
		
		public IAsyncResult BeginABContactDelete (Guid abId, ABContactCollection contacts, AsyncCallback callback, object asyncState)
		{
			return this.BeginInvoke ("ABContactDelete", new object[] { abId, contacts }, callback, asyncState);
		}
		
		public void EndABContactDelete (IAsyncResult asyncResult)
		{
			this.EndInvoke (asyncResult);
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABGroupAdd", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public ABGroupAddResult ABGroupAdd (Guid abId, ABGroupAddOptions groupAddOptions, ABGroupAddInfo groupInfo)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			object[] results = this.Invoke ("ABGroupAdd", new object[] { abId, groupAddOptions, groupInfo });
			ProcessServiceHeader ();
			return (ABGroupAddResult)results[0];
		}
		
		public IAsyncResult BeginABGroupAdd (Guid abId, ABGroupAddOptions groupAddOptions, ABGroupAddInfo groupInfo, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			return this.BeginInvoke ("ABGroupAdd", new object[] { abId, groupAddOptions, groupInfo }, callback, asyncState);
		}
		
		public ABGroupAddResult EndABGroupAdd (IAsyncResult asyncResult)
		{
			object[] results = this.EndInvoke (asyncResult);
			return (ABGroupAddResult)results[0];
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABGroupDelete", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public void ABGroupDelete (Guid abId, GroupFilter groupFilter)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Timer;
			this.Invoke ("ABGroupDelete", new object[] { abId, groupFilter });
			ProcessServiceHeader ();
		}
		
		public IAsyncResult BeginABGroupDelete (Guid abId, GroupFilter groupFilter, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.Timer;
			return this.BeginInvoke ("ABGroupDelete", new object[] { abId, groupFilter }, callback, asyncState);
		}
		
		public void EndABGroupDelete (IAsyncResult asyncResult)
		{
			this.EndInvoke (asyncResult);
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABGroupContactDelete", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public void ABGroupContactDelete (Guid abId, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts, GroupFilter groupFilter)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			this.Invoke ("ABGroupContactDelete", new object[] { abId, contacts, groupFilter });
			ProcessServiceHeader ();
		}
		
		public IAsyncResult BeginABGroupContactDelete (Guid abId, [XmlArray, XmlArrayItem ("Contact")] ABContactCollection contacts, GroupFilter groupFilter, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			return this.BeginInvoke ("ABGroupContactDelete", new object[] { abId, contacts, groupFilter }, callback, asyncState);
		}
		
		public void EndABGroupContactDelete (IAsyncResult asyncResult)
		{
			this.EndInvoke (asyncResult);
		}
		
		[SoapDocumentMethod ("http://www.msn.com/webservices/AddressBook/ABGroupUpdate", RequestNamespace=SoapConstants.nsAddressBook, ResponseNamespace=SoapConstants.nsAddressBook)]
		[SoapHeader ("appHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("authHeader", Direction=SoapHeaderDirection.In)]
		[SoapHeader ("serviceHeader", Direction=SoapHeaderDirection.Out)]
		[RequireSecurityTokens (SecurityToken.Contacts)]
		public void ABGroupUpdate (Guid abId, [XmlArray, XmlArrayItem ("Group")] ABGroupCollection groups)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			this.Invoke ("ABGroupUpdate", new object[] { abId, groups });
			ProcessServiceHeader ();
		}
		
		public IAsyncResult BeginABGroupUpdate (Guid abId, ABGroupCollection groups, AsyncCallback callback, object asyncState)
		{
			appHeader.PartnerScenario = ABPartnerScenario.GroupSave;
			return this.BeginInvoke ("ABGroupUpdate", new object[] { abId, groups }, callback, asyncState);
		}
		
		public void EndABGroupUpdate (IAsyncResult asyncResult)
		{
			this.EndInvoke (asyncResult);
		}
	}
}
